<template>
  <v-page
    ref="pageRef"
    v-model="refreshing"
    header-background="white"
    background="#f5f6fa"
    padding-top="24rpx"
    :loading="loading"
    :empty="state === 'finished' && !productList.length"
    empty-oss-src="empty-product.png"
    empty-text="暂无商品"
    @refresh="refreshHandle"
    @scroll="scrollHandle"
    @tolower="getProductList"
  >
    <template #header>
      <v-navbar
        title="店铺详情"
        native
      />
      <view class="merchant-pad">
        <template v-if="!loading">
          <v-image
            height="110rpx"
            width="110rpx"
            border-radius="50%"
            :src="merchant?.logo_image"
            mode="aspectFill"
          />
          <view class="merchant-info">
            <view class="main">
              {{ merchant?.name }}
            </view>
            <view class="sub">
              {{ `商品数量: ${total}` }}
            </view>
          </view>
        </template>
      </view>
      <view class="header">
        <template v-if="!loading">
          <view
            class="filter-item"
            :class="{ active: filterType === 'DEFAULT' }"
            @click="clickFilter('DEFAULT')"
          >
            <view class="label">
              默认
            </view>
          </view>
          <view
            class="filter-item"
            :class="{ active: filterType === 'PRICE' }"
            @click="clickFilter('PRICE')"
          >
            <view class="label">
              价格
            </view>
            <view class="sort-icon">
              <v-icon
                :active="filterType === 'PRICE' && filterSort === 'ASC'"
                size="15rpx"
                :custom-style="{ marginBottom: '-6rpx' }"
                active-src="@/static/icons/search-sort-arrow-active.svg"
                src="@/static/icons/search-sort-arrow.svg"
              />
              <v-icon
                :active="filterType === 'PRICE' && filterSort === 'DESC'"
                size="15rpx"
                :custom-style="{
                  transform: 'rotate(180deg)',
                  marginTop: '-6rpx'
                }"
                active-src="@/static/icons/search-sort-arrow-active.svg"
                src="@/static/icons/search-sort-arrow.svg"
              />
            </view>
          </view>
        </template>
      </view>
    </template>
    <template #default>
      <view class="product-list">
        <m-product-block
          v-for="(product, index) in productList"
          :key="index"
          :product="product"
          :display="index >= displayMinIndex && index < displayMaxIndex"
        />
      </view>
      <v-loadmore
        :state="state"
        @reload="getProductList"
      />
    </template>
  </v-page>
</template>

<script setup lang="ts">
import type VPage from '@/components/v-page/v-page.vue';

const loading = ref(true);
const merchantId = ref('');
const merchant = ref<MerchantVO>();
const getMerchant = async () => {
  const response = await $api.getMerchantId(merchantId.value);
  switch (response.__error) {
    case undefined:
      merchant.value = response.data;
      break;
    default:
      merchant.value = undefined;
  }
};
const record = async () => {
  if (!merchantId.value) return;
  $api.postMerchantView({ merchant_id: merchantId.value }, { notifyApiError: false });
};
onLoad(async (query) => {
  merchantId.value = query?.id as string;
  loading.value = true;
  await Promise.all([getMerchant(), getProductList(), record()]);
  loading.value = false;
  if (!merchant.value) uni.navigateBack();
});

const filterType = ref<'DEFAULT' | 'PRICE' | 'TIME'>('DEFAULT');
const filterSort = ref<'ASC' | 'DESC'>('ASC');
const clickFilter = (type: 'DEFAULT' | 'PRICE') => {
  filterType.value = type;
  if (type === 'PRICE' && filterSort.value === 'ASC') {
    filterSort.value = 'DESC';
  } else {
    filterSort.value = 'ASC';
  }
  refreshHandle();
};

const productList = ref<SpuVO[]>([]);
const total = ref(0);
const pageIndex = ref(1);
const state = ref<'loading' | 'finished' | 'error'>();
const getProductList = async () => {
  if (state.value !== undefined && state.value !== 'error') return;
  state.value = 'loading';
  const response = await $api.getSearchMerchant({
    page_no: pageIndex.value,
    page_size: 20,
    merchant_id: merchantId.value,
    sort: filterType.value,
    mode: filterSort.value
  });
  switch (response.__error) {
    case undefined:
      productList.value.push(...(response.data?.list ?? []));
      pageIndex.value++;
      if (productList.value.length >= response.data?.total) {
        state.value = 'finished';
      } else {
        state.value = undefined;
      }
      total.value = response.data.total;
      break;
    default:
      state.value = 'error';
  }
};

const refreshing = ref(false);
const refreshHandle = async () => {
  pageIndex.value = 1;
  productList.value = [];
  state.value = undefined;
  refreshing.value = true;
  await getProductList();
  refreshing.value = false;
};

const pageRef = ref() as Ref<InstanceType<typeof VPage>>;
const pageHeight = ref(0);
onMounted(async () => {
  pageHeight.value = await pageRef.value.getPageHeight(pageRef.value);
});
/** 虚拟列表逻辑 */
const rpxRatio = computed(() => {
  const system = uni.getSystemInfoSync();
  return 750 / system.windowWidth;
});
const scrollTop = ref(0);
const scrollHandle = (event: ScrollEvent) => {
  // 24rpx padding-top
  scrollTop.value = event.detail.scrollTop - 24 / rpxRatio.value;
};
/** 每行商品高度 */
const productBlockHeight = computed(() => {
  return rpxRatio.value ? 464 / rpxRatio.value : 0;
});
/** 最大可见行数 */
const maxDisplayLine = computed(() => {
  return pageHeight.value
    ? Math.ceil(pageHeight.value / productBlockHeight.value) + 2
    : 0;
});
/** 起始序号 */
const displayMinIndex = computed(() => {
  if (!productBlockHeight.value) return 0;
  const current = scrollTop.value;
  return Math.max(0, Math.floor(current / productBlockHeight.value) * 2);
});
/** 终止序号 */
const displayMaxIndex = computed(() => {
  if (!productBlockHeight.value) return 0;
  return displayMinIndex.value + maxDisplayLine.value * 2;
});
</script>

<style lang="scss" scoped>
.merchant-pad {
  height: 150rpx;
  padding: 0 32rpx;
  display: flex;
  align-items: center;
  gap: 28rpx;
  .merchant-info {
    flex: 1;
    min-width: 0;
    .main {
      font-size: 32rpx;
      font-weight: bold;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
      word-break: break-all;
    }
    .sub {
      margin-top: 12rpx;
      color: #666666;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
      word-break: break-all;
    }
  }
}
.header {
  padding: 0 24rpx;
  display: flex;
  align-items: center;
  gap: 16rpx;
  height: 70rpx;
  .filter-item {
    line-height: 70rpx;
    padding: 0 24rpx;
    display: flex;
    align-items: center;
    justify-content: center;
    gap: 8rpx;
    &.active {
      color: #ff2f3b;
    }
    .sort-icon {
      display: flex;
      flex-direction: column;
      align-items: center;
      justify-content: center;
      gap: 2rpx;
      .desc {
        transform-origin: center;
        transform: rotate(180deg);
      }
    }
  }
}

.product-list {
  display: flex;
  flex-wrap: wrap;
  gap: 16rpx 0;
  padding: 0 24rpx;
  justify-content: space-between;
}
</style>
